﻿#include "AF_Effect.h"

namespace AF
{
	Effect::Effect() :
		ATTRIB(Step)(0),
		ATTRIB(Reverse)(false),
		m_ERK(RK_UNKNOW),
		m_hFrame(NULL),
		m_nCurFm(0),
		m_pPackage(NULL),
		m_hImage(NULL),
		m_nStartID(0),
		m_nEndID(0),
		m_rClips(NULL)
	{
		m_nGType = GRAPHICS_EFFECT;
	}

	Effect::~Effect()
	{
		AF_DELETE(m_rClips);
	}

	bool Effect::Init(Bundle* pParam)
	{
		return OnInit(pParam);
	}

	bool Effect::Init(Package* pPackage, const UINT nStartID, const int nEndID, Bundle* pParam)
	{
		if(!Reset(pPackage, nStartID, nEndID))
			return false;
		return OnInit(pParam);
	}

	bool Effect::Init(Image* pImage, const UINT nWidthNum, const UINT nHeightNum, const UINT nFrameNum, Bundle* pParam)
	{
		if(!Reset(pImage, nWidthNum, nHeightNum, nFrameNum))
			return false;
		return OnInit(pParam);
	}

	void Effect::PlayNow()
	{
		PlayFree(m_nStartID, m_nEndID, ATTRIB(Loop), ATTRIB(Reverse));
	}

	void Effect::PlayTo(UINT nToFrame)
	{
		if(ATTRIB(Reverse) == false)
			PlayFree(m_nStartID, nToFrame, ATTRIB(Loop), false);
		else
			PlayFree(nToFrame, m_nEndID, ATTRIB(Loop), true);
	}

	void Effect::PlayFree(UINT nStartFrame, UINT nEndFrame, bool isLoop, bool isReverse)
	{
		m_Param.PutInteger(AF_PRM_EFFECT_START_i, nStartFrame);
		m_Param.PutInteger(AF_PRM_EFFECT_END_i, nEndFrame);
		m_Param.PutBoolean(AF_PRM_EFFECT_LOOP_b, isLoop);
		m_Param.PutBoolean(AF_PRM_EFFECT_REVERSE_b, isReverse);

		Play(&m_Param);
	}

	bool Effect::Reset(Package* pPackage, const UINT nStartID, const int nEndID)
	{
		AF_CHECK_R(pPackage != NULL, false);
		
		int _nEndID = nEndID;
		if(_nEndID < 0)
			_nEndID = pPackage->GetCount() - 1;

		m_pPackage = pPackage;
		m_nStartID = nStartID;
		m_nEndID = _nEndID;
		m_nCurFm = m_nStartID;

		m_ERK = RK_PACKAGE;

		// 检查包资源，并加载第一帧图像
		LoadPkgFrame(m_nStartID);
		if(m_hFrame == NULL)
		{
			return false;
		}

		return true;
	}

	bool Effect::Reset(Image* pImage, const UINT nWidthNum, const UINT nHeightNum, const UINT nFrameNum)
	{
		AF_CHECK_R(pImage != NULL, false);

		m_hImage = pImage->GetImageHandle();

		m_nStartID = 0;
		m_nEndID = AF_MIN_NUM(nWidthNum * nHeightNum, nFrameNum);
		m_rClips = AF_NEW_ARY(Rect, m_nEndID);

		ATTRIB(Size).nWidth = pImage->GetSize().nWidth / nWidthNum;
		ATTRIB(Size).nHeight = pImage->GetSize().nHeight / nHeightNum;
		for(int i = 0; i < (int)m_nEndID; i++)
		{
			m_rClips[i].Set(
				ATTRIB(Size).nWidth * (i % nWidthNum),
				ATTRIB(Size).nHeight * (i / nWidthNum),
				ATTRIB(Size).nWidth,
				ATTRIB(Size).nHeight);
		}

		m_ERK = RK_IMAGE;
		return true;
	}

	void Effect::SetFrame(UINT nFrameID)
	{
		AF_CHECK(GetState() == AS_STOP);

		m_nCurFm = nFrameID + m_nStartID;
		if(m_ERK == RK_PACKAGE)
		{
			if(m_nCurFm < m_nStartID || m_nCurFm > m_nEndID)
				m_nCurFm = m_nStartID;

			LoadPkgFrame(m_nCurFm);
		}
		else if(m_ERK == RK_IMAGE)
		{
			if(m_nCurFm >= m_nEndID)
				m_nCurFm = 0;
		}

	}

	void Effect::AddStep()
	{
		ATTRIB(Step)++;
	}

	bool Effect::OnPlay(Bundle* pParam)
	{
		AF_CHECK_R(pParam != NULL, false);

		if(m_ERK == RK_PACKAGE)
			AF_CHECK_R(m_pPackage != NULL, false);

		m_nStartFm = pParam->GetInteger(AF_PRM_EFFECT_START_i);
		m_nEndFm = pParam->GetInteger(AF_PRM_EFFECT_END_i);
		ATTRIB(Loop) = pParam->GetBoolean(AF_PRM_EFFECT_LOOP_b);
		ATTRIB(Reverse) = pParam->GetBoolean(AF_PRM_EFFECT_REVERSE_b);

		//		CF
		//		|
		//		V
		// SID------SF==========EF-----EID
		
		if(m_nStartFm < m_nStartID)
			m_nStartFm = m_nStartID;
		if(m_nEndFm > m_nEndID)
			m_nEndFm = m_nEndID;
		if(m_nStartFm >= m_nEndFm)
			return false;

		// 如果当前帧在区间之外
		if(m_nCurFm < m_nStartFm || m_nCurFm > m_nEndFm)
			m_nCurFm = m_nStartFm;

		// 根据正序反序，调整当前帧
		if(!ATTRIB(Reverse) && m_nCurFm == m_nEndFm)
			m_nCurFm = m_nStartFm;
		else if(ATTRIB(Reverse) && m_nCurFm == m_nStartFm)
			m_nCurFm = m_nEndFm;

		// 加载当前帧
		LoadPkgFrame(m_nCurFm);
		AF_CHECK_R(m_hFrame != NULL, false);

		return true;
	}

	bool Effect::OnUpdate()
	{
		if(ATTRIB(Reverse))
		{
			if(OnUpdateReverse() == false)
				return false;
		}
		else
		{
			m_nCurFm++;

			if(m_nCurFm > m_nEndFm)
			{
				m_nCurFm = m_nEndFm;
				if(GetLoop() == false)
				{
					return false;
				}
				m_nCurFm = m_nStartFm;
			}
		}

		LoadPkgFrame(m_nCurFm);
		AF_CHECK_R(m_hFrame != NULL, false);

		return true;
	}

	bool Effect::OnUpdateReverse()
	{
		m_nCurFm--;

		if(m_nCurFm < m_nStartFm)
		{
			m_nCurFm = m_nStartFm;
			if(GetLoop() == false)
			{
				return false;
			}
			m_nCurFm = m_nEndFm;
		}

		return true;
	}

	ImageHandle Effect::GetFrameImageHandle()
	{
		return m_hFrame;
	}

	Rect Effect::GetClip()
	{
		if(m_ERK == RK_PACKAGE)
		{
			return AF_RECT_NULL;
		}
		else if(m_ERK == RK_IMAGE)
		{
			return m_rClips[m_nCurFm];
		}
		else return AF_RECT_NULL;
	}

	void Effect::LoadPkgFrame(UINT nID)
	{
		if(m_ERK == RK_PACKAGE)
		{
			static char szName[128];
			static ImageInfo ii;

			AF_CHECK(m_pPackage != NULL);

			_SPRINTF(szName, "%d.bmp", nID);
			m_hFrame = m_pPackage->GetImageHandle(szName, ATTRIB(Size).nWidth, ATTRIB(Size).nHeight, ii);
		}
	}
}